﻿package com.dg.gaming.api.common
{
	import com.dg.gaming.api.common.msg.*;
	import com.ericfeminella.collections.ArrayList;
	import nanoxml.XMLElement;

	/**
	 * ...
	 * @author
	 */
	public class Game extends Observable implements ITransmittable
	{

		private static const XML_ATT_GAME_KEY:String="gameKey";
		private static const XML_ATT_MIN_PLAYERS:String="minPlayers";
		private static const XML_ATT_MAX_PLAYERS:String="maxPlayers";
		private static const XML_CUSTOM_GAME_PROPS:String="customGameProperties";
		private var customGamePropertiesTree:XMLElement=null;

		/** Game key <game title>-<version> e.g. chess. */
		protected var gameKey:String;

		/** List of users which are currently connected to the server. */
		protected var userList:UserList;

		/** List of tables current being played on this server. */
		protected var tableList:TableList;

		/** Minimum and maximum number of players on table. */
		private var minNumOfPlayers:int;
		private var maxNumOfPlayers:int;

		/**
		 * Constructor to a Game object.
		 *
		 * @param gameKey Game key
		 */
		public function init(gameKey:String, minNumOfPlayers:int, maxNumOfPlayers:int):void
		{
			this.gameKey=gameKey;

			// Create new list of users and list of tables
			userList=new UserList;
			tableList=new TableList;

			// Set min / max number of players
			this.minNumOfPlayers=minNumOfPlayers;
			this.maxNumOfPlayers=maxNumOfPlayers;
		}

		/**
		 * Game constructor which takes an XMLElement as a parameter.
		 *
		 * @param message
		 * @throws TransmissionException
		 */
		public function initXML(message:XMLElement):void
		{
			// Read game key and create empty userlist / tablelist.
			this.gameKey=message.getStringAttribute(XML_ATT_GAME_KEY);
			// Set min / max number of players
			this.minNumOfPlayers=message.getIntAttribute(XML_ATT_MIN_PLAYERS);
			this.maxNumOfPlayers=message.getIntAttribute(XML_ATT_MAX_PLAYERS);

			// Read child elements - userlist and tablelist
			var e:Array=ArrayList.createArrayList(message.chileds);
			for (var elem:*in e)
			{
				var childMessage:XMLElement=XMLElement(elem);

				if (childMessage.name == Msg.USER_LIST)
				{
					this.userList=new UserList;
					this.userList.initXml(childMessage);
				}
				else if (childMessage.name == Msg.TABLE_LIST)
				{
					this.tableList=new TableList(childMessage);
				}
				else if (childMessage.name == XML_CUSTOM_GAME_PROPS)
				{
					this.customGamePropertiesTree=XMLElement(childMessage.chileds[0]);
				}
			}

			// If no users / tables - create empty user and table lists
			if (userList == null)
			{
				userList=new UserList;
			}
			if (tableList == null)
			{
				tableList=new TableList;
			}
		}

		/**
		 * Return the key of the game.
		 *
		 * @return
		 */
		public function getKey():String
		{
			return gameKey;
		}

		/**
		 * Return the <i>game</i> part of the game key.
		 *
		 * @return
		 */
		public function getGameStr():String
		{
			return gameKey;
		}

		/**
		 * Return the minimum number of players in a game.
		 *
		 * @return    Max num of players.
		 */
		public function getMinNumOfPlayers():int
		{
			return minNumOfPlayers;
		}

		/**
		 * Return the minimum number of players in a game.
		 *
		 * @return    Max num of players.
		 */
		public function getMaxNumOfPlayers():int
		{
			return maxNumOfPlayers;
		}

		/**
		 * Returns the UserList object of current connected users.
		 *
		 * @return
		 */
		public function getUserList():UserList
		{
			return userList;
		}

		/**
		 * Returns the custom game properties for this game.
		 *
		 * @returnAn XML tree of custom properties
		 */
		public function getCustomGameProperties():XMLElement
		{
			return customGamePropertiesTree;
		}

		/**
		 * Set the userlist.
		 *
		 * @param userlist   New userlist which replaces the older one.
		 */
		public function setUserList(userlist:UserList):void
		{
			this.userList=userlist;
		}

		/**
		 * Set the table list.
		 *
		 * @param tableList  New tablelist which replaces the older one.
		 */
		public function setTableList(tableList:TableList):void
		{
			this.tableList=tableList;
		}

		/**
		 * Return the TableList object or table currently being played.
		 *
		 * @return
		 */
		public function getTableList():TableList
		{
			return tableList;
		}

		/**
		 * Set the custom game properties for this game.
		 * This is for server controllers to use to set custom properties
		 *
		 * @param custPropertiesAn XML tree of custom properties
		 */
		public function setCustomGameProperties(custProperties:XMLElement):void
		{
			customGamePropertiesTree=custProperties;
		}

		/**
		 * Return the game as a String.
		 *
		 * @see java.lang.Object#toString()
		 */
		public override function toString():String
		{
			return gameKey;
		}

		/**
		 * Flatten this object.
		 *
		 * @see com.dg.gaming.api.common.msg.ITransmittable#flatten()
		 */
		public function flatten():XMLElement
		{
			var message:XMLElement=new XMLElement;
			message.name=Msg.GAME;

			message.setAttribute(XML_ATT_GAME_KEY, gameKey);
			message.setIntAttribute(XML_ATT_MIN_PLAYERS, minNumOfPlayers);
			message.setIntAttribute(XML_ATT_MAX_PLAYERS, maxNumOfPlayers);

			if (userList.size() > 0)
			{
				message.addChild(userList.flatten());
			}
			if (tableList.size() > 0)
			{
				message.addChild(tableList.flatten());
			}

			if (customGamePropertiesTree != null)
			{
				/* Wrap the game's custom properties in a child element of
				 type XML_CUSTOM_GAME_PROPS */
				var custEl:XMLElement=new XMLElement;
				custEl.name=XML_CUSTOM_GAME_PROPS;
				custEl.addChild(customGamePropertiesTree);
				message.addChild(custEl);
			}

			return message;
		}
	}

}